package testJdk.nio.buffer;

import org.junit.Test;

import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.IntBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;

/**
 * @author cyd
 * @version 1.0.0
 * @date 2021/11/22 20:37
 */


public class TestBuffer {

    @Test
    public void test() throws Exception {
        // 创建随机读取流
        RandomAccessFile accessFile = new RandomAccessFile("D:\\WorkSpace\\demo\\src\\main\\java\\learn_jdk\\test_nio\\test.txt", "rw");
        // 创建文件管道
        FileChannel fileChannel = accessFile.getChannel();
        // 定义缓冲区
        ByteBuffer byteBuffer = ByteBuffer.allocate(48);
        // 第一次从管道中读取
        int read = fileChannel.read(byteBuffer);
        // 只要管道中没读完，就循环读取
        while (read != -1) {
            byteBuffer.flip();
            // 从缓冲区读取
            while (byteBuffer.hasRemaining()) {
                System.out.println((char) byteBuffer.get());
            }
            // 清空缓冲区
            byteBuffer.clear();
            // 再次从管道中读取，填充缓冲区
            read = fileChannel.read(byteBuffer);
        }
        // 关闭随机读取文件流
        accessFile.close();
    }

    @Test
    public void testIntBuffer() {
        // 分配新的 int 缓冲区，参数为缓冲区容量
        // 新缓冲区的当前位置将为零，其界限(限制位置)将为其容量。
        // 它将具有一个底层实现数组，其数组偏移量将为零。
        IntBuffer intBuffer = IntBuffer.allocate(8);

        for (int i = 0; i < intBuffer.capacity(); i++) {
            // 将给定整数写入此缓冲区的当前位置，当前位置递增
            int j = 2 * (i + 1);
            intBuffer.put(j);
        }
        // 重设此缓冲区，将限制设置为当前位置，然后将当前位置设置为 0
        intBuffer.flip();
        // 查看在当前位置和限制位置之间是否有元素
        while (intBuffer.hasRemaining()) {
            // 读取此缓冲区当前位置的整数，然后当前位置递增
            int q = intBuffer.get();
            System.out.print(q + " ");
        }
    }

    @Test
    public void testSlice() {
        ByteBuffer buffer = ByteBuffer.allocate(10);
        // 缓冲区中的数据 0-9
        for (int i = 0; i < buffer.capacity(); i++) {
            buffer.put((byte) i);
        }
        // 创建子缓冲区
        buffer.position(3);
        buffer.limit(7);
        ByteBuffer slice = buffer.slice();
        // 改变子缓冲区的内容
        for (int i = 0; i < slice.capacity(); i++) {
            byte b = slice.get(i);
            b *= 10;
            slice.put(i, b);
        }
        // buffer重新定位
        buffer.position(0);
        buffer.limit(buffer.capacity());

        while (buffer.hasRemaining()) {
            System.out.println(buffer.get());
        }
    }

    @Test
    public void testReadOnly() {
        ByteBuffer buffer = ByteBuffer.allocate(10);
        // 缓冲区中的数据 0-9
        for (int i = 0; i < buffer.capacity(); i++) {
            buffer.put((byte) i);
        }
        // 创建只读缓冲区
        ByteBuffer readOnlyBuffer = buffer.asReadOnlyBuffer();
        // 改变原缓冲区的内容
        for (int i = 0; i < buffer.capacity(); i++) {
            byte b = buffer.get(i);
            b *= 10;
            buffer.put(i, b);
        }
        // readOnlyBuffer重新定位
        readOnlyBuffer.position(0);
        readOnlyBuffer.limit(buffer.capacity());
        // 只读缓冲区的内容也随之改变
        while (readOnlyBuffer.hasRemaining()) {
            System.out.println(readOnlyBuffer.get());
        }
    }

    static private final int start = 0;
    static private final int size = 1024;
    static private final String path = "D:\\WorkSpace\\demo\\src\\main\\java\\learn_jdk\\test_nio\\test.txt";

    @Test
    public void testMapFile() throws Exception {
        RandomAccessFile raf = new RandomAccessFile(path, "rw");
        FileChannel fc = raf.getChannel();
        MappedByteBuffer mbb = fc.map(FileChannel.MapMode.READ_WRITE, start, size);
        mbb.put(0, (byte) 97);
        mbb.put(1023, (byte) 122);
        raf.close();
    }
}
